{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "initial_id",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": "##基于信息熵的决策树"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:06.259425Z",
     "start_time": "2025-03-30T07:40:06.028350Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from sklearn.datasets import load_iris\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "from sklearn.metrics import accuracy_score\n",
    "import numpy as np\n",
    "from scipy.stats import ttest_rel"
   ],
   "id": "73d3f00195f482a",
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:08.123008Z",
     "start_time": "2025-03-30T07:40:08.100291Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 加载数据集\n",
    "data = load_iris()\n",
    "X = data.data\n",
    "y = data.target"
   ],
   "id": "a9c6bc97cacf99dd",
   "outputs": [],
   "execution_count": 2
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:10.039387Z",
     "start_time": "2025-03-30T07:40:10.036142Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 存储准确率\n",
    "accuracies_entropy = []\n",
    "accuracies_entropy_pruned = []"
   ],
   "id": "2cc653c5ff6291a5",
   "outputs": [],
   "execution_count": 3
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:11.928163Z",
     "start_time": "2025-03-30T07:40:11.921409Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 划分训练集和测试集\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)"
   ],
   "id": "2138a3a3ce7f501a",
   "outputs": [],
   "execution_count": 4
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:14.302525Z",
     "start_time": "2025-03-30T07:40:14.291088Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 未剪枝决策树（基于信息熵）\n",
    "tree_entropy = DecisionTreeClassifier(criterion='entropy', random_state=42)\n",
    "tree_entropy.fit(X_train, y_train)\n",
    "y_pred_entropy = tree_entropy.predict(X_test)\n",
    "accuracy_entropy = accuracy_score(y_test, y_pred_entropy)\n",
    "print(f\"未剪枝决策树（信息熵）的准确率: {accuracy_entropy}\")"
   ],
   "id": "d934bd81311f45cd",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "未剪枝决策树（信息熵）的准确率: 0.9777777777777777\n"
     ]
    }
   ],
   "execution_count": 5
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:17.189523Z",
     "start_time": "2025-03-30T07:40:17.184003Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 预剪枝决策树（基于信息熵）\n",
    "tree_entropy_pruned = DecisionTreeClassifier(criterion='entropy', min_samples_split=5, min_samples_leaf=2, random_state=42)\n",
    "tree_entropy_pruned.fit(X_train, y_train)\n",
    "y_pred_entropy_pruned = tree_entropy_pruned.predict(X_test)\n",
    "accuracy_entropy_pruned = accuracy_score(y_test, y_pred_entropy_pruned)\n",
    "print(f\"预剪枝决策树（信息熵）的准确率: {accuracy_entropy_pruned}\")"
   ],
   "id": "e084a36836f7d1a0",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预剪枝决策树（信息熵）的准确率: 1.0\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:20.049899Z",
     "start_time": "2025-03-30T07:40:20.040752Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 后剪枝决策树（基于信息熵）\n",
    "# 后剪枝需要先构建完整的树，然后通过成本复杂度剪枝\n",
    "tree_entropy_full = DecisionTreeClassifier(criterion='entropy', random_state=42)\n",
    "tree_entropy_full.fit(X_train, y_train)"
   ],
   "id": "79649ba88dd2610c",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DecisionTreeClassifier(criterion='entropy', random_state=42)"
      ],
      "text/html": [
       "<style>#sk-container-id-1 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: #000;\n",
       "  --sklearn-color-text-muted: #666;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-1 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-1 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: flex;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "  align-items: start;\n",
       "  justify-content: space-between;\n",
       "  gap: 0.5em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label .caption {\n",
       "  font-size: 0.6rem;\n",
       "  font-weight: lighter;\n",
       "  color: var(--sklearn-color-text-muted);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-1 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-1 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 0.5em;\n",
       "  text-align: center;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-1 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>DecisionTreeClassifier(criterion=&#x27;entropy&#x27;, random_state=42)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>DecisionTreeClassifier</div></div><div><a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.6/modules/generated/sklearn.tree.DecisionTreeClassifier.html\">?<span>Documentation for DecisionTreeClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></div></label><div class=\"sk-toggleable__content fitted\"><pre>DecisionTreeClassifier(criterion=&#x27;entropy&#x27;, random_state=42)</pre></div> </div></div></div></div>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:22.938811Z",
     "start_time": "2025-03-30T07:40:22.929221Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 获取成本复杂度参数\n",
    "path = tree_entropy_full.cost_complexity_pruning_path(X_train, y_train)\n",
    "ccp_alphas = path.ccp_alphas"
   ],
   "id": "75fc9a9c34c1012",
   "outputs": [],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:25.259409Z",
     "start_time": "2025-03-30T07:40:25.252237Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 应用成本复杂度剪枝\n",
    "tree_entropy_post_pruned = DecisionTreeClassifier(criterion='entropy', ccp_alpha=ccp_alphas[-5], random_state=42)\n",
    "tree_entropy_post_pruned.fit(X_train, y_train)\n",
    "y_pred_entropy_post_pruned = tree_entropy_post_pruned.predict(X_test)\n",
    "accuracy_entropy_post_pruned = accuracy_score(y_test, y_pred_entropy_post_pruned)\n",
    "print(f\"后剪枝决策树（信息熵）的准确率: {accuracy_entropy_post_pruned}\")"
   ],
   "id": "906c0aa2e462b1b7",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "后剪枝决策树（信息熵）的准确率: 0.9777777777777777\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "###基于基尼指数的决策树",
   "id": "e5e149cc4fdc9f52"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:30.229788Z",
     "start_time": "2025-03-30T07:40:30.221692Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 未剪枝决策树（基于基尼指数）\n",
    "tree_gini = DecisionTreeClassifier(criterion='gini', random_state=42)\n",
    "tree_gini.fit(X_train, y_train)\n",
    "y_pred_gini = tree_gini.predict(X_test)\n",
    "accuracy_gini = accuracy_score(y_test, y_pred_gini)\n",
    "print(f\"未剪枝决策树（基尼指数）的准确率: {accuracy_gini}\")"
   ],
   "id": "96128a35df0c37c7",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "未剪枝决策树（基尼指数）的准确率: 1.0\n"
     ]
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:33.173076Z",
     "start_time": "2025-03-30T07:40:33.166997Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 预剪枝决策树（基于基尼指数）\n",
    "tree_gini_pruned = DecisionTreeClassifier(criterion='gini', min_samples_split=5, min_samples_leaf=2, random_state=42)\n",
    "tree_gini_pruned.fit(X_train, y_train)\n",
    "y_pred_gini_pruned = tree_gini_pruned.predict(X_test)\n",
    "accuracy_gini_pruned = accuracy_score(y_test, y_pred_gini_pruned)\n",
    "print(f\"预剪枝决策树（基尼指数）的准确率: {accuracy_gini_pruned}\")"
   ],
   "id": "4a9a3e3a2b28e575",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预剪枝决策树（基尼指数）的准确率: 1.0\n"
     ]
    }
   ],
   "execution_count": 12
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:36.380529Z",
     "start_time": "2025-03-30T07:40:36.371364Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 后剪枝决策树（基于基尼指数）\n",
    "tree_gini_full = DecisionTreeClassifier(criterion='gini', random_state=42)\n",
    "tree_gini_full.fit(X_train, y_train)"
   ],
   "id": "ce3230c1c338be64",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DecisionTreeClassifier(random_state=42)"
      ],
      "text/html": [
       "<style>#sk-container-id-2 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: #000;\n",
       "  --sklearn-color-text-muted: #666;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-2 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-2 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-2 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: flex;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "  align-items: start;\n",
       "  justify-content: space-between;\n",
       "  gap: 0.5em;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 label.sk-toggleable__label .caption {\n",
       "  font-size: 0.6rem;\n",
       "  font-weight: lighter;\n",
       "  color: var(--sklearn-color-text-muted);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-2 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-2 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-2 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-2 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-2 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 0.5em;\n",
       "  text-align: center;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-2 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>DecisionTreeClassifier(random_state=42)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" checked><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>DecisionTreeClassifier</div></div><div><a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.6/modules/generated/sklearn.tree.DecisionTreeClassifier.html\">?<span>Documentation for DecisionTreeClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></div></label><div class=\"sk-toggleable__content fitted\"><pre>DecisionTreeClassifier(random_state=42)</pre></div> </div></div></div></div>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 13
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:38.880814Z",
     "start_time": "2025-03-30T07:40:38.876825Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 获取成本复杂度参数\n",
    "path = tree_gini_full.cost_complexity_pruning_path(X_train, y_train)\n",
    "ccp_alphas = path.ccp_alphas"
   ],
   "id": "a9b0adef4eb0d624",
   "outputs": [],
   "execution_count": 14
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:40.933955Z",
     "start_time": "2025-03-30T07:40:40.925316Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 应用成本复杂度剪枝\n",
    "tree_gini_post_pruned = DecisionTreeClassifier(criterion='gini', ccp_alpha=ccp_alphas[-5], random_state=42)\n",
    "tree_gini_post_pruned.fit(X_train, y_train)\n",
    "y_pred_gini_post_pruned = tree_gini_post_pruned.predict(X_test)\n",
    "accuracy_gini_post_pruned = accuracy_score(y_test, y_pred_gini_post_pruned)\n",
    "print(f\"后剪枝决策树（基尼指数）的准确率: {accuracy_gini_post_pruned}\")"
   ],
   "id": "f049fb456fd845c2",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "后剪枝决策树（基尼指数）的准确率: 1.0\n"
     ]
    }
   ],
   "execution_count": 15
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:40:46.284188Z",
     "start_time": "2025-03-30T07:40:46.279810Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 使用配对 t 检验比较未剪枝和后剪枝的准确率\n",
    "t_stat, p_value = ttest_rel([accuracy_gini], [accuracy_gini_post_pruned])\n",
    "print(f\"未剪枝与后剪枝的 p 值: {p_value}\")"
   ],
   "id": "ecfc6cbf8b43f221",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "未剪枝与后剪枝的 p 值: nan\n"
     ]
    }
   ],
   "execution_count": 17
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "##基于对率回归的决策树",
   "id": "1825287db6adf616"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:51:32.361846Z",
     "start_time": "2025-03-30T07:51:32.353901Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.metrics import accuracy_score\n",
    "import numpy as np\n",
    "\n",
    "class LogisticRegressionTree:\n",
    "    def __init__(self, criterion='gini', max_depth=None, min_samples_split=2, min_samples_leaf=1):\n",
    "        self.criterion = criterion\n",
    "        self.max_depth = max_depth\n",
    "        self.min_samples_split = min_samples_split\n",
    "        self.min_samples_leaf = min_samples_leaf\n",
    "        self.tree = None\n",
    "\n",
    "    def fit(self, X, y):\n",
    "        self.tree = self._build_tree(X, y, depth=0)\n",
    "    \n",
    "    def _build_tree(self, X, y, depth):\n",
    "        # 基本情况：如果达到最大深度或样本数不足，则创建叶节点\n",
    "        if self.max_depth is not None and depth >= self.max_depth:\n",
    "            return self._create_leaf_node(X, y)\n",
    "        \n",
    "        if len(y) < self.min_samples_split:\n",
    "            return self._create_leaf_node(X, y)\n",
    "        \n",
    "        # 检查是否只有一个类别\n",
    "        unique_classes = np.unique(y)\n",
    "        if len(unique_classes) == 1:\n",
    "            return self._create_leaf_node(X, y)\n",
    "        \n",
    "        # 找到最佳分裂特征和阈值\n",
    "        best_feature, best_threshold = self._find_best_split(X, y)\n",
    "        \n",
    "        if best_feature is None:\n",
    "            return self._create_leaf_node(X, y)\n",
    "        \n",
    "        # 分裂数据集\n",
    "        left_mask = X[:, best_feature] <= best_threshold\n",
    "        right_mask = X[:, best_feature] > best_threshold\n",
    "        \n",
    "        # 递归构建子树\n",
    "        left_child = self._build_tree(X[left_mask], y[left_mask], depth+1)\n",
    "        right_child = self._build_tree(X[right_mask], y[right_mask], depth+1)\n",
    "        \n",
    "        return {\n",
    "            'feature': best_feature,\n",
    "            'threshold': best_threshold,\n",
    "            'left': left_child,\n",
    "            'right': right_child\n",
    "        }\n",
    "    \n",
    "    def _create_leaf_node(self, X, y):\n",
    "        # 检查是否只有一个类别\n",
    "        unique_classes, counts = np.unique(y, return_counts=True)\n",
    "        if len(unique_classes) == 1:\n",
    "            # 如果只有一个类别，直接返回该类别的值\n",
    "            return unique_classes[0]\n",
    "        \n",
    "        # 创建逻辑回归模型作为叶节点\n",
    "        model = LogisticRegression(max_iter=1000)\n",
    "        model.fit(X, y)\n",
    "        return model\n",
    "    \n",
    "    def _find_best_split(self, X, y):\n",
    "        best_gain = -np.inf\n",
    "        best_feature = None\n",
    "        best_threshold = None\n",
    "        \n",
    "        for feature in range(X.shape[1]):\n",
    "            # 对特征值进行排序\n",
    "            sorted_values = np.sort(np.unique(X[:, feature]))\n",
    "            # 生成可能的阈值\n",
    "            thresholds = (sorted_values[:-1] + sorted_values[1:]) / 2\n",
    "            \n",
    "            for threshold in thresholds:\n",
    "                # 分裂数据集\n",
    "                left_y = y[X[:, feature] <= threshold]\n",
    "                right_y = y[X[:, feature] > threshold]\n",
    "                \n",
    "                # 计算信息增益\n",
    "                gain = self._calculate_information_gain(y, left_y, right_y)\n",
    "                \n",
    "                if gain > best_gain:\n",
    "                    best_gain = gain\n",
    "                    best_feature = feature\n",
    "                    best_threshold = threshold\n",
    "        \n",
    "        return best_feature, best_threshold\n",
    "    \n",
    "    def _calculate_information_gain(self, parent_y, left_y, right_y):\n",
    "        # 计算父节点的信息熵\n",
    "        parent_entropy = self._entropy(parent_y)\n",
    "        \n",
    "        # 计算子节点的信息熵\n",
    "        left_entropy = self._entropy(left_y)\n",
    "        right_entropy = self._entropy(right_y)\n",
    "        \n",
    "        # 计算信息增益\n",
    "        weight_left = len(left_y) / len(parent_y)\n",
    "        weight_right = len(right_y) / len(parent_y)\n",
    "        info_gain = parent_entropy - (weight_left * left_entropy + weight_right * right_entropy)\n",
    "        \n",
    "        return info_gain\n",
    "    \n",
    "    def _entropy(self, y):\n",
    "        # 计算信息熵\n",
    "        _, counts = np.unique(y, return_counts=True)\n",
    "        probabilities = counts / len(y)\n",
    "        entropy = -np.sum(probabilities * np.log2(probabilities))\n",
    "        return entropy\n",
    "    \n",
    "    def predict(self, X):\n",
    "        predictions = []\n",
    "        for x in X:\n",
    "            predictions.append(self._predict_single(x, self.tree))\n",
    "        return np.array(predictions)\n",
    "    \n",
    "    def _predict_single(self, x, tree):\n",
    "        if isinstance(tree, LogisticRegression):\n",
    "            return tree.predict([x])[0]\n",
    "        elif isinstance(tree, np.int64) or isinstance(tree, int):\n",
    "            return tree\n",
    "        \n",
    "        if x[tree['feature']] <= tree['threshold']:\n",
    "            return self._predict_single(x, tree['left'])\n",
    "        else:\n",
    "            return self._predict_single(x, tree['right'])"
   ],
   "id": "98ee6abd39bf947a",
   "outputs": [],
   "execution_count": 25
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T08:07:50.825657Z",
     "start_time": "2025-03-30T08:07:50.808740Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from sklearn.datasets import load_iris\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "from sklearn.metrics import accuracy_score\n",
    "import numpy as np\n",
    "from scipy.stats import ttest_rel\n",
    "\n",
    "# 加载数据集\n",
    "data = load_iris()\n",
    "X = data.data\n",
    "y = data.target\n",
    "\n",
    "# 设置实验次数\n",
    "n_experiments = 30\n",
    "\n",
    "# 存储准确率\n",
    "accuracies_unpruned = []\n",
    "accuracies_pruned = []\n",
    "\n",
    "for _ in range(n_experiments):\n",
    "    # 划分训练集和测试集\n",
    "    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=np.random.randint(100))\n",
    "\n",
    "# 未剪枝决策树\n",
    "tree_unpruned = DecisionTreeClassifier(criterion='entropy', random_state=42)\n",
    "tree_unpruned.fit(X_train, y_train)\n",
    "y_pred_unpruned = tree_unpruned.predict(X_test)\n",
    "accuracy_unpruned = accuracy_score(y_test, y_pred_unpruned)\n",
    "accuracies_unpruned.append(accuracy_unpruned)\n",
    "print(f\"未剪枝决策树的准确率：{accuracy_unpruned}\")"
   ],
   "id": "a5b9b45503d2302",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "未剪枝决策树的准确率：0.9333333333333333\n"
     ]
    }
   ],
   "execution_count": 39
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T08:07:54.537944Z",
     "start_time": "2025-03-30T08:07:54.531810Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 预剪枝决策树（基于对率回归）\n",
    "tree_pruned = DecisionTreeClassifier(criterion='entropy', min_samples_split=5, min_samples_leaf=2, random_state=42)\n",
    "tree_pruned.fit(X_train, y_train)\n",
    "y_pred_pruned = tree_pruned.predict(X_test)\n",
    "accuracy_pruned = accuracy_score(y_test, y_pred_pruned)\n",
    "accuracies_pruned.append(accuracy_pruned)\n",
    "print(f\"预剪枝决策树（对率回归）的准确率: {accuracy_pruned}\")"
   ],
   "id": "5267f2331ff87f36",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预剪枝决策树（对率回归）的准确率: 0.9333333333333333\n"
     ]
    }
   ],
   "execution_count": 40
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T07:53:01.224965Z",
     "start_time": "2025-03-30T07:53:01.193825Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 后剪枝决策树（基于对率回归）\n",
    "# 后剪枝需要更复杂的实现，这里我们简单地通过限制最大深度来模拟后剪枝的效果\n",
    "tree_logistic_post_pruned = LogisticRegressionTree(criterion='entropy', max_depth=2)\n",
    "tree_logistic_post_pruned.fit(X_train, y_train)\n",
    "y_pred_logistic_post_pruned = tree_logistic_post_pruned.predict(X_test)\n",
    "accuracy_logistic_post_pruned = accuracy_score(y_test, y_pred_logistic_post_pruned)\n",
    "print(f\"后剪枝决策树（对率回归）的准确率: {accuracy_logistic_post_pruned}\")"
   ],
   "id": "dd8203822d2b6d08",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "后剪枝决策树（对率回归）的准确率: 0.9777777777777777\n"
     ]
    }
   ],
   "execution_count": 28
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-30T08:09:43.997491Z",
     "start_time": "2025-03-30T08:09:43.930761Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from sklearn.datasets import load_iris\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "from sklearn.metrics import accuracy_score\n",
    "import numpy as np\n",
    "from scipy.stats import ttest_rel\n",
    "\n",
    "# 加载数据集\n",
    "data = load_iris()\n",
    "X = data.data\n",
    "y = data.target\n",
    "\n",
    "# 设置实验次数\n",
    "n_experiments = 30\n",
    "\n",
    "# 存储准确率\n",
    "accuracies_unpruned = []\n",
    "accuracies_pruned = []\n",
    "\n",
    "for _ in range(n_experiments):\n",
    "    # 划分训练集和测试集\n",
    "    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=np.random.randint(100))\n",
    "    \n",
    "    # 未剪枝决策树\n",
    "    tree_unpruned = DecisionTreeClassifier(criterion='entropy', random_state=42)\n",
    "    tree_unpruned.fit(X_train, y_train)\n",
    "    y_pred_unpruned = tree_unpruned.predict(X_test)\n",
    "    accuracy_unpruned = accuracy_score(y_test, y_pred_unpruned)\n",
    "    accuracies_unpruned.append(accuracy_unpruned)\n",
    "    \n",
    "    # 预剪枝决策树\n",
    "    tree_pruned = DecisionTreeClassifier(criterion='entropy', min_samples_split=5, min_samples_leaf=2, random_state=42)\n",
    "    tree_pruned.fit(X_train, y_train)\n",
    "    y_pred_pruned = tree_pruned.predict(X_test)\n",
    "    accuracy_pruned = accuracy_score(y_test, y_pred_pruned)\n",
    "    accuracies_pruned.append(accuracy_pruned)\n",
    "\n",
    "# 使用配对 t 检验比较未剪枝和预剪枝的准确率\n",
    "t_stat, p_value = ttest_rel(accuracies_unpruned, accuracies_pruned)\n",
    "print(f\"未剪枝与预剪枝的 p 值: {p_value}\")"
   ],
   "id": "9d096592d755dbc3",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "未剪枝与预剪枝的 p 值: 0.20178586998488046\n"
     ]
    }
   ],
   "execution_count": 45
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
